package com.example.myapplication.flow

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.myapplication.User
import com.orhanobut.logger.Logger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*

import kotlinx.coroutines.launch
import java.io.IOException

class FlowViewModel0912 : ViewModel() {
    val status = MutableLiveData<Any>()
    fun filter() {
        viewModelScope.launch {
            val result = mutableListOf<Int>()
            (1..5).asFlow().filter {
                it % 2 == 0
            }.toList(result)
            status.postValue(result)
        }
    }

    fun map() {

        viewModelScope.launch {
            var list = mutableListOf<User>()
            list.add(User("1"))
            list.add(User("2"))
            list.add(User("3"))
//            flowOf(list)


            var maplist = list.asFlow().map {
                "${it.name} +map"
            }.toList()
//            Logger.d(maplist)

            flowOf(1, 2, 3).flowOn(Dispatchers.Unconfined).flatMapConcat {
                flowOf(it.toString() + " map")
            }.flowOn(Dispatchers.Main).collect { value ->
                Logger.d(value)
            }
        }

    }

    fun zip() {
        viewModelScope.launch {
            var f1 = (1..5)
            var f2 = mutableListOf("a", "b", "c", "d")
            val zip = f1.zip(f2) { v1, v2 ->
                var list = mutableListOf<Any>()
                list.add(v1)
                list.add(v2)
                return@zip list
            }
            Logger.d(zip)


            f1.asFlow().collectIndexed { index, value ->
                Logger.d("index=$index  value $value")
            }
            f1.asFlow().last()
            f1.asFlow().toList()
            f1.asFlow().toSet()
            f1.asFlow().lastOrNull()
            f1.asFlow().first()
            f1.asFlow().firstOrNull()
            f1.asFlow().single()
            f1.asFlow().singleOrNull()
            f1.asFlow().count()
            f1.asFlow().withIndex().collect()
            f1.asFlow().filterIsInstance<User>().collect {

            }
            f1.asFlow().filterNot { it < 1 }.collect()
            f1.asFlow().filterNotNull().collect()
            f1.asFlow().drop(2).count()
            f1.asFlow().dropWhile { it > 3 }.count()
            f1.asFlow().take(3).collect()
            f1.asFlow().takeWhile { it > 3 }.collect()
            f1.asFlow().debounce(1000).collect()
            f1.asFlow().distinctUntilChangedBy { it == 3 }.collect()
            f1.asFlow().distinctUntilChanged().collect()
            f1.asFlow().combine(f2.asFlow()) { f1, f2 ->

            }.collect {

            }
            f1.asFlow().combineTransform(f2.asFlow()) { f1, f2 ->
                emit(f1.toString() + f2)
            }.collect()
            listOf(f1.asFlow(), f2.asFlow()).merge().collect()
            flow {
                emit(f1.asFlow())
                emit(f2.asFlow())
            }.flattenConcat().collect()


            flow {
                emit(f1.asFlow())
                emit(f2.asFlow())
            }.flattenMerge(3).collect()

            f1.asFlow().flatMapConcat {
                f2.asFlow()
            }.collect {

            }
            f1.asFlow().flatMapLatest {
                f2.asFlow()
            }.collect {

            }



            f1.asFlow().onEmpty {
//                emit("当流完成却没有发出任何元素时回调。 可以用来兜底.。")
            }
            f1.asFlow().toCollection(mutableListOf())

//            flow {
//                emitAll(flowOf(emptyList()))
//            }

        }


    }

    suspend fun retry() {
        flow<Int> {
            emit(1)
            throw IOException("")
        }.retry(2) { e ->
            if (e is IOException) {
                true
            } else {
                false
            }
        }.collect {
            Logger.d(it)
        }

        flow<Int> {
            emit(2)
            throw IOException("2")
        }.retryWhen { cause, attempt ->
            if (attempt > 4) {
                return@retryWhen false
            }
            cause is IOException
        }

        flowOf(1, 2, 4).onEach {
            Logger.d(it)
        }.buffer().collect {
            Logger.d("collect==" + it)
        }

    }

}